// @Author EthanScriptOn
// @Desc
package config_processor_management

import (
	"errors"
	"gitee.com/fatzeng/srf_switch_basic_components/custom_exp"
	"gitee.com/fatzeng/srf_switch_basic_components/identity"
	"gitee.com/fatzeng/srf_switch_basic_components/processor"
	"gitee.com/fatzeng/srf_switch_basic_components/resource"
	"gitee.com/fatzeng/srf_switch_config/config_define"
	"gitee.com/fatzeng/srf_switch_config/config_processor"
	"gitee.com/fatzeng/srf_switch_config/config_source_loader_management"
	"math"
	"reflect"
)

type SimpleParseProcessorManager struct {
	resourceManagerUpGradationInstance resource.ResourceManagerUpGradation
	resourceProcessorEntityIdentity    identity.IdentityInformation
	isCover                            bool
}

func (s *SimpleParseProcessorManager) AddProcessor(processor processor.Processor, processorEnum []config_define.ConfigSourceType, priority int) error {
	entity := config_processor.ResourceProcessorEntity{
		IdentityInformation: s.resourceProcessorEntityIdentity,
		ResourceProcessor:   processor,
		EntityPriority:      priority,
		SupportedList:       processorEnum,
	}
	levels := make([]resource.ResourceLevel, 0)
	for _, sourceType := range processorEnum {
		levels = append(levels, resource.ResourceLevel(sourceType))
	}
	return s.resourceManagerUpGradationInstance.AddResource(&entity, levels, s.isCover)
}

func (s *SimpleParseProcessorManager) CreateProcessor() (err error) {
	getList, err := config_source_loader_management.GetSupportedList()
	if err != nil {
		return
	}
	for processType, processEnums := range s.CreateProcessorMapping(getList) {
		newProcessor, err := processor.MakeProcessor(processType)
		if err != nil {
			return
		}
		if err = newProcessor.Initialization(); err != nil {
			return err
		}
		if err = s.AddProcessor(newProcessor, processEnums, math.MaxInt); err != nil {
			return
		}
	}
	return
}

func (s *SimpleParseProcessorManager) CreateProcessorMapping(supportList map[config_define.ConfigSourceType]*config_source_loader_management.SourceProcessorConfiguration) map[reflect.Type][]config_define.ConfigSourceType {
	processorMapping := make(map[reflect.Type][]config_define.ConfigSourceType)
	for sourceType, configuration := range supportList {
		processEnums, ok := processorMapping[configuration.ProcessorType]
		if !ok {
			processEnums = make([]config_define.ConfigSourceType, 0)
		}
		processEnums = append(processEnums, sourceType)
		processorMapping[configuration.ProcessorType] = processEnums
	}
	return processorMapping
}

func (s *SimpleParseProcessorManager) RemoveProcessorWithConfigSourceType(configSourceType config_define.ConfigSourceType) error {
	return s.resourceManagerUpGradationInstance.DelResourceWithLevels([]resource.ResourceLevel{resource.ResourceLevel(configSourceType)})
}

func (s *SimpleParseProcessorManager) RemoveProcessor(processorKey interface{}) error {
	identifier := processorKey
	return s.resourceManagerUpGradationInstance.DelResourceWithId(identifier)
}

func (s *SimpleParseProcessorManager) GetAllProcessor(configSourceType config_define.ConfigSourceType) ([]processor.Processor, error) {
	resourceEntityList, err := s.resourceManagerUpGradationInstance.FoundResourceWithLevels([]resource.ResourceLevel{resource.ResourceLevel(configSourceType)})
	if err != nil {
		return nil, err
	}
	processors := make([]processor.Processor, 0)
	for _, resourceEntity := range resourceEntityList {
		resourceProcessorEntity, ok := resourceEntity.(*config_processor.ResourceProcessorEntity)
		if !ok {
			return nil, errors.New("resource entity type error need *ResourceProcessorEntity")
		}
		processors = append(processors, resourceProcessorEntity.ResourceProcessor)
	}
	return processors, nil
}

func (s *SimpleParseProcessorManager) GetAppropriateProcessor(processorKey interface{}) (processor.Processor, error) {
	configSourceType, ok := processorKey.(config_define.ConfigSourceType)
	if !ok {
		return nil, errors.New("processor key type error need config_config_define.ConfigSourceType")
	}
	processor, err := s.GetAllProcessor(configSourceType)
	if err != nil {
		return nil, err
	}
	if len(processor) == 0 {
		return nil, custom_exp.GenerateNoResourceError(configSourceType, errors.New("not found processor"))
	}
	return processor[0], nil
}

func (s *SimpleParseProcessorManager) GetProcessor(processorKey interface{}) (processor.Processor, error) {
	identifier := processorKey
	resourceEntity, err := s.resourceManagerUpGradationInstance.FoundResourceWithId(identifier)
	if err != nil {
		return nil, err
	}
	resourceProcessorEntity, ok := resourceEntity.(*config_processor.ResourceProcessorEntity)
	if !ok {
		return nil, errors.New("resource entity type error need *ResourceProcessorEntity")
	}
	return resourceProcessorEntity.ResourceProcessor, nil
}
